package com.compass.doctor.ui.login


import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.text.SpannableStringBuilder
import android.text.Spanned
import android.text.TextPaint
import android.text.method.HideReturnsTransformationMethod
import android.text.method.LinkMovementMethod
import android.text.method.PasswordTransformationMethod
import android.text.style.ClickableSpan
import android.view.View
import android.widget.EditText
import android.widget.TextView
import androidx.annotation.RequiresApi
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import com.compass.doctor.R
import com.compass.doctor.base.BaseVBActivity
import com.compass.doctor.databinding.ActivityLoginBinding
import com.compass.doctor.dialog.AgreementMessageDialog
import com.compass.doctor.ui.MainActivity
import com.compass.doctor.ui.WebDetailActivity
import com.compass.framework.dialog.CommonMessageDialog
import com.compass.framework.ext.countDownCoroutines
import com.compass.framework.ext.onClick
import com.compass.framework.ext.textChangeFlow
import com.compass.framework.manager.UserInfoManager
import com.compass.framework.toast.TipsToast
import com.compass.framework.utils.DeviceInfoUtils
import com.compass.framework.utils.LogUtil
import com.compass.framework.utils.StatusBarSettingHelper
import com.compass.framework.utils.getColorFromResource
import com.compass.framework.utils.getStringFromResource
import com.netease.nimlib.sdk.NIMClient
import com.netease.nimlib.sdk.Observer
import com.netease.nimlib.sdk.RequestCallback
import com.netease.nimlib.sdk.auth.AuthService
import com.netease.nimlib.sdk.auth.AuthServiceObserver
import com.netease.nimlib.sdk.auth.ClientType
import com.netease.nimlib.sdk.auth.OnlineClient
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach

/**
 * @desc   登录
 */
class LoginActivity : BaseVBActivity<ActivityLoginBinding>() {
    private var isShowPassword = true
    private var isClick = true
    private lateinit var loginViewModel: LoginViewModel

    private lateinit var otherClient: OnlineClient
    companion object {
        fun start(context: Context) {
            val intent = Intent(context, LoginActivity::class.java)
            context.startActivity(intent)
        }
    }

    override fun initView(savedInstanceState: Bundle?) {
        setTheme(R.style.Transparent)//设置半透明试登录页面
        StatusBarSettingHelper.setStatusBarTranslucent(this)
        StatusBarSettingHelper.statusBarLightMode(this@LoginActivity, true)
        initAgreement()
        initListener()
        mBinding.etPassword.transformationMethod = HideReturnsTransformationMethod.getInstance()
    }


    override fun initData() {
        loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java]
        loginViewModel.loginLiveData.observe(this) { info ->
            //登录成功
            info?.let {
                //再请求登录云信
                UserInfoManager.saveAccessToken(it.accessToken)
                UserInfoManager.saveRefreshToken(it.refreshToken)
                UserInfoManager.saveUserType(it.type)
                UserInfoManager.saveImUserAccount(it.wyyxAccId)
                UserInfoManager.saveImToken(it.wyyxToken)
                loginViewModel.loginIm(UserInfoManager.getImUserAccount(), UserInfoManager.getImUserToken())
            }?:kotlin.run {
                dismissLoading()
            }
        }
        loginViewModel.loginImLiveData.observe(this) { loginfo ->
            loginfo?.let {
//                kickOtherClient()
                TipsToast.showTips(R.string.success_login)
                MainActivity.start(this, 0)
                finish()
            }
            dismissLoading()
        }
        loginViewModel.smsCodeLiveData.observe(this){
            //倒计时
            countDownCoroutines(59, lifecycleScope, onTick = {
                isClick=false
                mBinding.tvForgetPassword.setTextColor(getColorFromResource(R.color.color_999999))
                mBinding.tvForgetPassword.text = getString(R.string.sms_tip, it.plus(1).toString())
            }) {
                isClick=true
                mBinding.tvForgetPassword.setTextColor(getColorFromResource(R.color.color_2e344a))
                mBinding.tvForgetPassword.text="获取验证码"
            }

        }
    }

    private fun initListener() {
        mBinding.ivPasswordToggle.onClick {
            setPasswordHide()
        }
        mBinding.tvForgetPassword.onClick {
            if (!isClick){
                return@onClick
            }
            val phone = mBinding.etPhone.text.toString()
            val phoneEnable = !phone.isNullOrEmpty() && phone.length == 11
            if (isValidPhoneNumber(phone)&&phoneEnable) {
                loginViewModel.geSmsCode(phone)
            }else{
                showToast("请输入正确的手机号码")
            }

        }
        mBinding.tvLogin.onClick {
            toLogin()
        }
        mBinding.imgClose.onClick {
            finish()
        }
        setEditTextChange(mBinding.etPhone)
        setEditTextChange(mBinding.etPassword)
        mBinding.cbAgreement.setOnCheckedChangeListener { _, _ ->
            updateLoginState()
        }

        //监听其它端的登录状态，保证在登录成功以后，将其它端的登录给踢掉
//        NIMClient.getService(AuthServiceObserver::class.java)
//            .observeOtherClients(otherClientsObserver,true)

    }
    private val otherClientsObserver = Observer< List<OnlineClient>>() { onlineClients ->
        if(onlineClients == null || onlineClients.isEmpty()){
            return@Observer
        }
        otherClient = onlineClients[0]
        LogUtil.d("登录的设备数据是")
        LogUtil.d("ip = ${otherClient.clientIp} , type = ${otherClient.clientType}," +
                " os = ${otherClient.os} , customType = ${otherClient.customClientType}, ")
//        for (client in onlineClients){
//            LogUtil.d("登录的设备数据是")
//            LogUtil.d("ip = ${client.clientIp} , type = ${client.clientType}," +
//                    " os = ${client.os} , customType = ${client.customClientType}, ")
//        }
//
//        //只需要处理安卓和ios上登录的情况
//        when(onlineClient.clientType){
//            ClientType.Windows->{
//                LogUtil.d("other client is windows login")
//            }
//            ClientType.iOS->{
////                LogUtil.d("other client is ios login")
////                showToast("账号已在其他端登录")
//                //退出云信账号
////                LiveDataBus.get().with(LOGIN_FAILURE).postValue(LOGIN_FAILURE)
//            }
//            ClientType.Android->{
////                showToast("账号已在其他端登录")
//                //退出云信账号
////                LiveDataBus.get().with(LOGIN_FAILURE).postValue(LOGIN_FAILURE)
////                kickOtherClient(onlineClient)
//                LogUtil.d("other client is android login")
//            }
//        }
    }

    /**
     * 将其它客户端踢下线
     */
    private fun kickOtherClient(){
        if(::otherClient.isInitialized){
            NIMClient.getService(AuthService::class.java).kickOtherClient(otherClient).setCallback(object :
                RequestCallback<Void> {
                override fun onSuccess(result: Void?) {
                    LogUtil.d("other devices are successfully kicked. ")
                }

                override fun onFailed(code: Int) {
                    LogUtil.d("other devices are failed kicked. ")
                    LogUtil.d("failed：code $code ")
                }

                override fun onException(exception: Throwable?) {
                    LogUtil.d("other devices are exception kicked. ")
                }

            })
        }
    }

    private  fun isValidPhoneNumber(phoneNumber: String): Boolean {
        val pattern = Regex("^1[3456789]\\d{9}$") // 定义手机号码的正则表达式规则
        return pattern.matches(phoneNumber)
    }

    /**
     * 更新登录按钮状态
     */
    private fun updateLoginState() {
        val phone = mBinding.etPhone.text.toString()
        val phoneEnable = !phone.isNullOrEmpty() && phone.length == 11
        val password = mBinding.etPassword.text.toString()
        val passwordEnable = !password.isNullOrEmpty()


        mBinding.tvLogin.isSelected = phoneEnable && passwordEnable
    }

    /**
     * 监听EditText文本变化
     */
    private fun setEditTextChange(editText: EditText) {
        editText.textChangeFlow()
//                .filter { it.isNotEmpty() }
            .debounce(300)
            //.flatMapLatest { searchFlow(it.toString()) }
            .flowOn(Dispatchers.IO)
            .onEach {
                updateLoginState()
            }
            .launchIn(lifecycleScope)
    }

    /**
     * 去登录
     */
    private fun toLogin() {
        val userName = mBinding.etPhone.text?.trim()?.toString()
        val password = mBinding.etPassword.text?.trim()?.toString()

        if (userName.isNullOrEmpty() || userName.length < 11) {
            TipsToast.showTips(getStringFromResource(R.string.error_phone_number))
            return
        }
        if (password.isNullOrEmpty()) {
            TipsToast.showTips(R.string.error_input_password)
            return
        }
        if (!mBinding.cbAgreement.isChecked) {
            agreement(userName, password)
            return
        }
           login(userName, password)


    }

    private fun login(userName: String, password: String){
        DeviceInfoUtils.init(this)
        showLoading()
        loginViewModel.login(userName, password)
    }

    private fun agreement(userName: String, password: String){
        AgreementMessageDialog.Builder(this)
            .setTitle(getStringFromResource(com.compass.framework.R.string.dialog_tips_title))
            .setConfirm("同意并继续")
            .setCancel(getString(com.compass.framework.R.string.default_cancel))
            .setonCancelListener {
                it?.dismiss()
            }
            .setonConfirmListener {
                mBinding.cbAgreement.isChecked=true
                login(userName, password)
                it?.dismiss()
            }.create().show()
    }
    /**
     * 密码是否可见
     */
    private fun setPasswordHide() {
        isShowPassword = !isShowPassword
        if (isShowPassword) {
            mBinding.ivPasswordToggle.setImageResource(R.mipmap.ic_psw_invisible)
            mBinding.etPassword.transformationMethod = HideReturnsTransformationMethod.getInstance()
        } else {
            mBinding.etPassword.transformationMethod = PasswordTransformationMethod.getInstance()
            mBinding.ivPasswordToggle.setImageResource(R.mipmap.ic_psw_visible)
        }
        mBinding.etPassword.setSelection(mBinding.etPassword.length())
    }

    /**
     * 初始化协议点击
     */
    private fun initAgreement() {
       val agreement = getStringFromResource(R.string.login_agreement)
        try {
            mBinding.cbAgreement.movementMethod = LinkMovementMethod.getInstance()
            val spaBuilder = SpannableStringBuilder(agreement)
            val privacySpan = getStringFromResource(R.string.login_privacy_agreement)
            val serviceSpan = getStringFromResource(R.string.login_user_agreement)
            spaBuilder.setSpan(
                object : ClickableSpan() {
                    override fun onClick(widget: View) {
                        (widget as TextView).highlightColor =
                            getColorFromResource(com.compass.framework.R.color.transparent)
                        WebDetailActivity.start(
                            context = this@LoginActivity,
                            url = com.compass.framework.constant.POLICY,
                            title = "隐私政策")

                    }

                    @RequiresApi(Build.VERSION_CODES.M)
                    override fun updateDrawState(ds: TextPaint) {
                        super.updateDrawState(ds)
                        ds.color = getColorFromResource(R.color.color_0165b8)
                        ds.isUnderlineText = false
                        ds.clearShadowLayer()
                    }
                },
                spaBuilder.indexOf(privacySpan),
                spaBuilder.indexOf(privacySpan) + privacySpan.length,
                Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
            )
            spaBuilder.setSpan(
                object : ClickableSpan() {
                    override fun onClick(widget: View) {
                        (widget as TextView).highlightColor =
                            getColorFromResource(com.compass.framework.R.color.transparent)
                        WebDetailActivity.start(
                            context = this@LoginActivity,
                            url = com.compass.framework.constant.SERVICE,
                            title = "服务协议")
                    }

                    @RequiresApi(Build.VERSION_CODES.M)
                    override fun updateDrawState(ds: TextPaint) {
                        super.updateDrawState(ds)
                        ds.color = getColorFromResource(R.color.color_0165b8)
                        ds.isUnderlineText = false
                        ds.clearShadowLayer()
                    }
                },
                spaBuilder.indexOf(serviceSpan),
                spaBuilder.indexOf(serviceSpan) + serviceSpan.length,
                Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
            )

            mBinding.cbAgreement.setText(spaBuilder, TextView.BufferType.SPANNABLE)
        } catch (e: Exception) {
            LogUtil.e(e)
            mBinding.cbAgreement.text = agreement
        }
    }

    override fun onDestroy() {
        super.onDestroy()
//        NIMClient.getService(AuthServiceObserver::class.java)
//            .observeOtherClients(otherClientsObserver,false)
    }

}